﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using NUnit.Framework;

namespace Hallenberg.Web.Test
{
    [TestFixture]
    public class RoleProviderTest
    {
        [SetUp]
        public void MyTestInitialize()
        {
            ((MemoryRoleProvider)Roles.Provider).Reset();
            ((MemoryMembershipProvider)Membership.Provider).Reset();
        }

        [Test]
        public void Web_AddUsersToRoles()
        {
            Roles.CreateRole("Administrator");
            Roles.CreateRole("User");

            Membership.CreateUser("Rasmus", "SecretPassword");

            Roles.AddUsersToRoles(new string[] { "Rasmus" }, new string[] { "Administrator", "User" });

            string[] userRoles = Roles.GetRolesForUser("Rasmus");
            Assert.AreEqual(true, userRoles[0] == "Administrator");
            Assert.AreEqual(true, userRoles[1] == "User");

        }

        [Test]
        public void Web_CreateRole()
        {
            Roles.CreateRole("Administrator");
            Roles.CreateRole("User");

            string[] allRoles = Roles.GetAllRoles();

            Assert.AreEqual(2, allRoles.Length);
            Assert.AreEqual(true, allRoles[0] == "Administrator");
            Assert.AreEqual(true, allRoles[1] == "User");
        }

        [Test]
        public void Web_DeleteRole()
        {
            Roles.CreateRole("Administrator");
            Roles.CreateRole("User");

            string[] allRoles = Roles.GetAllRoles();

            Assert.AreEqual(2, allRoles.Length);
            Assert.AreEqual(true, allRoles[0] == "Administrator");
            Assert.AreEqual(true, allRoles[1] == "User");

            Roles.DeleteRole("Administrator");

            allRoles = Roles.GetAllRoles();
            Assert.AreEqual(1, allRoles.Length);
            Assert.AreEqual(true, allRoles[0] == "User");
        }

        [Test]
        public void Web_RoleExists()
        {
            Roles.CreateRole("Administrator");
            Roles.CreateRole("User");

            Assert.AreEqual(true, Roles.RoleExists("Administrator"));
            Assert.AreEqual(true, Roles.RoleExists("User"));
            Assert.AreEqual(false, Roles.RoleExists("Guest User"));
        }

        [Test]
        public void Web_RemoveUsersFromRoles()
        {
            Web_CreateRole();
            Web_AddUsersToRoles();

            Roles.RemoveUsersFromRoles(new string[] { "Rasmus" }, new string[] { "Administrator" });

            string[] roles = Roles.GetRolesForUser("Rasmus");
            Assert.AreEqual(1, roles.Length);
            Assert.AreEqual("User", roles[0]);
        }

        [Test]
        public void Web_GetRolesForUser()
        {
            Roles.CreateRole("Administrator");
            Roles.CreateRole("User");
            Roles.CreateRole("Guest");

            Membership.CreateUser("test_user_1", "no_pwd");
            Membership.CreateUser("test_user_2", "no_pwd");
            Membership.CreateUser("test_user_3", "no_pwd");


            Roles.AddUsersToRole(new string[] { "test_user_1", "test_user_2" }, "Administrator");
            Roles.AddUsersToRole(new string[] { "test_user_3" }, "User");
            Roles.AddUsersToRole(new string[] { "test_user_1" }, "Guest");

            string[] administrators = Roles.GetRolesForUser("test_user_1");

            Assert.AreEqual("Administrator", administrators[0]);
            Assert.AreEqual("Guest", administrators[1]);
        }

        [Test]
        public void Web_UserInRoles()
        {
            Roles.CreateRole("Administrator");
            Roles.CreateRole("User");
            Roles.CreateRole("Guest");

            Membership.CreateUser("test_user_1", "no_pwd");
            Membership.CreateUser("test_user_2", "no_pwd");
            Membership.CreateUser("test_user_3", "no_pwd");

            Roles.AddUsersToRole(new string[] { "test_user_1", "test_user_2" }, "Administrator");
            Roles.AddUsersToRole(new string[] { "test_user_3" }, "User");
            Roles.AddUsersToRole(new string[] { "test_user_1" }, "Guest");

            Assert.AreEqual(true, Roles.IsUserInRole("test_user_1", "Administrator"));
            Assert.AreEqual(true, Roles.IsUserInRole("test_user_2", "Administrator"));
            Assert.AreEqual(true, Roles.IsUserInRole("test_user_1", "Guest"));
        }

        [Test]
        public void Web_FindUsersInRole()
        {
            Roles.CreateRole("Administrator");
            Roles.CreateRole("User");
            Roles.CreateRole("Guest");

            Membership.CreateUser("test_user_1", "no_pwd");
            Membership.CreateUser("test_user_2", "no_pwd");
            Membership.CreateUser("test_user_3", "no_pwd");

            Roles.AddUsersToRole(new string[] { "test_user_1", "test_user_2" }, "Administrator");
            Roles.AddUsersToRole(new string[] { "test_user_3" }, "User");
            Roles.AddUsersToRole(new string[] { "test_user_1" }, "Guest");

            string[] administrators = Roles.FindUsersInRole("Administrator", "test_user_1");

            Assert.AreEqual(1, administrators.Length);
            Assert.AreEqual("test_user_1", administrators[0]);

            administrators = Roles.FindUsersInRole("Administrator", "test_user");

            Assert.AreEqual(2, administrators.Length);
            Assert.AreEqual("test_user_1", administrators[0]);
            Assert.AreEqual("test_user_2", administrators[1]);
        }

        [Test]
        public void Web_DeleteRole_Fail()
        {
            try
            {
                Roles.DeleteRole(null);
                Assert.Fail("Method should throw on null argument");
            }
            catch { }

            try
            {
                Roles.DeleteRole(string.Empty);
                Assert.Fail("Method should throw on null argument");
            }
            catch { }

            Assert.AreEqual(false, Roles.DeleteRole("No such role"));

            Membership.CreateUser("test_user_1", "no_pwd");
            Roles.CreateRole("Administrator");

            Roles.AddUserToRole("test_user_1", "Administrator");

            try
            {
                Roles.DeleteRole("Administrator", true);
                Assert.Fail("Method should have thrown an exceptions, as test_user_1 is assigned the role");
            }
            catch { }
        }

        [Test]
        public void Web_AddUsersToRoles_Fail()
        {
            Roles.CreateRole("Administrator");
            Roles.CreateRole("User");

            try
            {
                Roles.AddUserToRole(null, null);
                Assert.Fail("Method should have thrown an exception");
            }
            catch { }

            try
            {
                Roles.AddUserToRole("TestUser", null);
                Assert.Fail("Method should have thrown an exception");
            }
            catch { }

            try
            {
                Roles.AddUserToRole("TestUser", "Administrator");
                Assert.Fail("Method should have thrown an exception");
            }
            catch (InvalidOperationException)
            {
                // Expected exception when user does not exist.
            }
            catch (Exception)
            {
                Assert.Fail("Unexpected exception");
            }

            Membership.CreateUser("TestUser", "no_pwd");

            try
            {
                Roles.AddUserToRole("TestUser", "NoSuchRole");
                Assert.Fail("Method should throw an exception because role does not exist");
            }
            catch (InvalidOperationException)
            {
                // Expected operation.
            }
            catch
            {
                Assert.Fail("Unexpected exception");
            }
        }
    }

}
